﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace LiJ.Common.Extention
{
    /// <summary>
    /// 枚举扩展方法类
    /// </summary>
    public static class EnumExtention
    {
        private static ConcurrentDictionary<string, Dictionary<string, string>> _enumDirs = new ConcurrentDictionary<string, Dictionary<string, string>>();

        /// <summary>
        /// 获取描述
        /// </summary>
        /// <param name="en">枚举对象</param>
        /// <param name="isFlag">是否二进制取和</param>
        /// <param name="operate">多个描述分隔符</param>
        /// <returns></returns>
        public static string GetDescript(this Enum en, bool isFlag = false, string operate = ",")
        {
            Dictionary<string, string> dictionary = en.GetType().ToEnumDirs(true);
            int current = (int)Enum.Parse(en.GetType(), en.ToString());
            if (isFlag)
            {
                StringBuilder stringBuilder = new StringBuilder();
                foreach (KeyValuePair<string, string> item in dictionary)
                {
                    int num = item.Key.ToInt32(0);
                    if ((num & current) == num)
                    {
                        if (stringBuilder.Length != 0)
                        {
                            stringBuilder.Append(operate);
                        }
                        stringBuilder.Append(item.Value);
                    }
                }
                return stringBuilder.ToString();
            }
            KeyValuePair<string, string> keyValuePair = dictionary.FirstOrDefault((KeyValuePair<string, string> e) => e.Key == current.ToString());
            if (keyValuePair.Key != null)
            {
                return keyValuePair.Value;
            }
            return "不存在的枚举值";
        }

        /// <summary>
        /// 获取枚举字典列表
        /// </summary>
        /// <param name="enType">枚举类型</param>
        /// <param name="isIntValue">返回枚举值是否是int类型</param>
        /// <returns></returns>
        public static Dictionary<string, string> ToEnumDirs(this Type enType, bool isIntValue = true)
        {
            if (!enType.GetTypeInfo().IsEnum)
            {
                throw new ArgumentException("获取枚举字典，参数必须是枚举类型！");
            }
            string key = enType.FullName + isIntValue;
            _enumDirs.TryGetValue(key, out var dictionary);
            if (dictionary != null)
            {
                return dictionary.Copy();
            }
            dictionary = new Dictionary<string, string>();
            foreach (object value in Enum.GetValues(enType))
            {
                string name = Enum.GetName(enType, value);
                string key2 = isIntValue ? ((int)value).ToString() : value.ToString();
                FieldInfo declaredField = enType.GetTypeInfo().GetDeclaredField(name);
                LDescriptAttribute lDescriptAttribute = ((object)declaredField != null) ? ((MemberInfo)declaredField).GetCustomAttribute<LDescriptAttribute>() : null;
                dictionary.Add(key2, (lDescriptAttribute == null) ? name : lDescriptAttribute.Description);
            }
            _enumDirs.TryAdd(key, dictionary);
            return dictionary.Copy();
        }

        /// <summary>
        ///   拷贝字典
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        private static Dictionary<string, string> Copy(this Dictionary<string, string> source)
        {
            return source.ToDictionary((KeyValuePair<string, string> sou) => sou.Key, (KeyValuePair<string, string> sou) => sou.Value);
        }
    }
}